package com.actionpals.components.controls
{
	import com.actionpals.components.core.UITextComponent;
	import com.actionpals.enum.InvalidationType;
	import com.actionpals.enum.ScrollPolicy;
	import com.actionpals.events.ComponentEvent;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	import flash.events.TextEvent;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;
	import flash.text.TextLineMetrics;
	import flash.ui.Keyboard;
	
	public class BaseTextField extends UITextComponent
	{
		protected var _background:DisplayObject;
		protected var _field:TextField;
		protected var _upState:DisplayObject;
		protected var _disabledState:DisplayObject;
		protected var _editable:Boolean = true;
		protected var _horizontalScrollPolicy:String = ScrollPolicy.AUTO;
		protected var _html:Boolean = false;
		protected var _savedHTML:String;
		
		public function BaseTextField()
		{
			tabEnabled = true;
			super();
		}
		
		public function get field():TextField
		{
			return _field;
		}
		public function set field( value:TextField ):void
		{
			_field = value;
		}
		
		public function get upState():DisplayObject
		{
			return _upState;
		}
		public function set upState( value:DisplayObject ):void
		{
			_upState = value;
		}
		
		public function get disabledState():DisplayObject
		{
			return _disabledState ? _disabledState : upState;
		}
		public function set disabledState( value:DisplayObject ):void
		{
			_disabledState = value;
		}
		
		
		public function get alwaysShowSelection():Boolean
		{
			return field.alwaysShowSelection;
		}
		public function set alwaysShowSelection( value:Boolean ):void
		{
			field.alwaysShowSelection = value;	
		}
		
		public function get autoSize():String
		{
			return field.autoSize;
		}
		public function set autoSize( value:String ):void
		{
			field.autoSize = value;	
		}
		
		public function get condenseWhite():Boolean
		{
			return field.condenseWhite
		}
		public function set condenseWhite( value:Boolean ):void
		{
			field.condenseWhite = value;
			invalidate( InvalidationType.DATA );
		}
		
		public function get displayAsPassword():Boolean
		{
			return field.displayAsPassword;
		}
		public function set displayAsPassword( value:Boolean ):void
		{
			field.displayAsPassword = value;
		}
		
		public function get editable():Boolean
		{
			return _editable;
		}
		public function set editable( value:Boolean ):void
		{
			_editable = value;
			invalidate( InvalidationType.STATE );
		}
		
		public override function set enabled( value:Boolean ):void
		{
			super.enabled = value;
			mouseChildren = enabled;
		}
		
		public function get horizontalScrollPolicy():String
		{
			return _horizontalScrollPolicy;
		}
		public function set horizontalScrollPolicy( value:String ):void
		{
			_horizontalScrollPolicy = value;
			invalidate( InvalidationType.SIZE );
		}
		
		public function get horizontalScrollPosition():int
		{
			return field.scrollH;
		}
		public function set horizontalScrollPosition( value:int ):void
		{
			field.scrollH = value;
		}
		
		public function get htmlText():String
		{
			return field.htmlText;
		}
		public function set htmlText( value:String ):void
		{
			if( value == "" )
			{ 
				text = "";
				return;
			}
			_html = true;
			_savedHTML = value;
			field.htmlText = value;
			invalidate( InvalidationType.DATA );
			invalidate( InvalidationType.STYLES );
		}
		
		public function get length():int
		{
			return field.text.length;
		}
		
		public function get maxChars():int
		{
			return field.maxChars;
		}
		public function set maxChars( value:int ):void
		{
			field.maxChars = value;
		}
		
		public function get maxHorizontalScrollPosition():int
		{
			return field.maxScrollH;
		}
		
		public function get restrict():String
		{
			return field.restrict;
		}
		public function set restrict( value:String ):void
		{
			if( value == "" )
			{ 
				value = null;
			}
			field.restrict = value;
		}
		
		public function get selectionBeginIndex():int
		{
			return field.selectionBeginIndex;
		}
		
		public function get selectionEndIndex():int
		{
			return field.selectionEndIndex;
		}
		
		public override function get tabIndex():int
		{
			return field.tabIndex;
		}
		public override function set tabIndex( value:int ):void
		{
			field.tabIndex = value;
		}
		
		public function get text():String
		{
			return field.text;
		}
		public function set text( value:String ):void
		{
			field.text = value;
			_html = false;
			invalidate( InvalidationType.DATA );
			invalidate( InvalidationType.STYLES );
		}
		
		public function get textHeight():Number
		{
			return field.textHeight;
		}
		
		public function get textWidth():Number
		{
			return field.textWidth;
		}
		
		public function appendText( text:String ):void
		{
			field.appendText( text );
			invalidate( InvalidationType.DATA );
		}
		
		public function getLineMetrics( index:int ):TextLineMetrics
		{
			return field.getLineMetrics( index );
		}
		
		protected function setEmbedFont():void
		{
			field.embedFonts = embedFonts;
		}
		
		public function setSelection( beginIndex:int, endIndex:int ):void
		{
			field.setSelection( beginIndex, endIndex );
		}
		
		protected function updateTextFieldType():void
		{
			field.type = ( enabled && editable ) ? TextFieldType.INPUT : TextFieldType.DYNAMIC;
			field.selectable = ( enabled && editable );
		}
		
		
		protected override function init():void
		{
			super.init();
			tabChildren = true;
			field = new TextField();
			addChild( field );
			updateTextFieldType();
			field.addEventListener( TextEvent.TEXT_INPUT, handleTextInput, false, 0, true );
			field.addEventListener( Event.CHANGE, handleChange, false, 0, true );
			field.addEventListener( KeyboardEvent.KEY_DOWN, handleKeyDown, false, 0, true );
		}
		
		protected override function draw():void
		{
			if( isInvalid( InvalidationType.STATE ) )
			{
				updateTextFieldType();
			}
			
			if( isInvalid( InvalidationType.STYLES ) )
			{				
				setEmbedFont();				
			}
			
			if( isInvalid( InvalidationType.STYLES, InvalidationType.STATE ) )
			{
				drawTextFormat();
				drawBackground();
				invalidate( InvalidationType.SIZE );
			}
			
			if( isInvalid( InvalidationType.SIZE, InvalidationType.DATA ) )
			{
				drawLayout();
			}
			
			super.draw();
		}
		
		protected function drawBackground():void
		{
			var state:String = enabled ? "upState" : "disabledState";
			var bg:DisplayObject = _background;
			_background = this[ state ];
			if( _background == null ) { return; }
			if( !width ) width = _background.width;
			if( !height ) height = _background.height;
			addChildAt( _background, 0 );
			if( bg != null && bg != _background && contains( bg ) ) { removeChild( bg ); }
		}
		
		protected function drawLayout():void
		{
			if( _background != null )
			{
				_background.width = width;
				_background.height = height;
			}
			setTextSize( width, height, paddingLeft, paddingRight );
		}
		
		protected function drawTextFormat():void
		{
			var tf:TextFormat = enabled ? textFormat : disabledTextFormat;
			try{ field.setTextFormat( tf ); } catch( e:Error ){}
			var defaultTF:TextFormat = enabled ? defaultTextFormat : defaultDisabledTextFormat;
			try{ field.defaultTextFormat = defaultTF; } catch( e:Error ){}
			
			setEmbedFont();
			if( _html ) { field.htmlText = _savedHTML; }
		}
		
		protected override function isOurFocus( target:DisplayObject ):Boolean
		{
			return target == field || super.isOurFocus( target );
		}
		
		protected function needHScroll():Boolean
		{
			if( horizontalScrollPolicy == ScrollPolicy.OFF ) { return false; }
			if( horizontalScrollPolicy == ScrollPolicy.ON ) { return true; }
			return ( field.maxScrollH > 0 );
		}
		
		public override function setFocus():void
		{
			stage.focus = field;
		}
		
		protected function setTextSize( width:Number, height:Number, paddingLeft:Number, paddingRight:Number ):void
		{
			var w:Number = width - paddingLeft - paddingRight;
			var h:Number = height - paddingLeft - paddingRight;
			
			if( w != field.width && width != 0 )
			{
				field.width = w;
			}
			if( h != field.height )
			{
				if( height != 0 ) field.height = h;
				else field.height = field.textHeight;
			}			
		}
		
		
		protected override function focusInHandler( evt:FocusEvent ):void
		{
			if( evt.target == this )
			{
				stage.focus = field;
			}
			super.focusInHandler( evt );
		}
		
		protected override function focusOutHandler( evt:FocusEvent ):void
		{
			setSelection( 0, 0 );
			super.focusOutHandler( evt );
		}
		
		protected function handleChange( evt:Event ):void
		{
			evt.stopPropagation();
			dispatchEvent( new Event( Event.CHANGE, true ) );
			invalidate( InvalidationType.DATA );
		}
		
		protected function handleKeyDown( evt:KeyboardEvent ):void
		{
			if( evt.keyCode == Keyboard.ENTER )
			{
				dispatchEvent( new ComponentEvent( ComponentEvent.ENTER, true ) );
			}
		}
		
		protected function handleTextInput( evt:TextEvent ):void
		{
			evt.stopPropagation();
			dispatchEvent( new TextEvent( TextEvent.TEXT_INPUT, true, false, evt.text ) );
		}
		
	}
}